﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RedmineToolBar.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using RedmineToolBar.Redmine.Configuration;

namespace RedmineToolBar.Redmine.Downloader
{
    public class RedmineDownloader
    {

        private RedmineConfiguration Config { get; set; }
        private const string ELECA_QUERY = "/queries.json";
        private const string QUERY = "/issues.json?query_id={0}&limit=1000000";
        private const string QUERY_SINGLE_PRJ = "/issues.json?query_id={0}&project_id={1}&limit=1000000";



        public RedmineDownloader(RedmineConfiguration config)
        {
            Config = config;
        }

        public List<RedmineQuery> GetRedmineQuery()
        {
            List<RedmineQuery> retList = new List<RedmineQuery>();
            var result = DownloadRedmineElements(Config.Url + ELECA_QUERY, Config.User, Config.Pwd, "queries");

            foreach (var item in result)
            {
                var name = ExtractValueFromJtoken(item, "name", "");
                var project = ExtractValueFromJtoken(item, "project_id", "");
                var id = ExtractValueFromJtoken(item, "id", "");


                retList.Add(new RedmineQuery()
                {
                    project_id = project,
                    name = name,
                    id = int.Parse(id)
                });
            }
            return retList;

        }

        private T ExecuteQuery<T>()
        {
            T elements;
            var result = DownloadRedmineJson(Config.Url + string.Format(QUERY, Config.QueryId), Config.User, Config.Pwd, "issues");
            if (Config.QueryProjectId != "" && result == null)
            {
                result = DownloadRedmineJson(Config.Url + string.Format(QUERY_SINGLE_PRJ, Config.QueryId, Config.QueryProjectId), Config.User, Config.Pwd, "issues");
            }

            elements = JsonConvert.DeserializeObject<T>(result);
            return elements;
        }


        public void UpdateSheet(Worksheet worksheet)
        {
            var elements = ExecuteQuery<RootObject>();
            string range = ("A{0}:XDF{1}");
            for (int i = 1; i <= elements.issues.Count; i++)
            {

                try
                {
                    var a = worksheet.get_Range(string.Format(range, i, i));

                    a.Cells[RedmineFields.assigned_to].Value2 = elements.issues[i - 1].assigned_to != null ? elements.issues[i - 1].assigned_to.name : "";
                    a.Cells[RedmineFields.author].Value2 = elements.issues[i - 1].author.name;
                    a.Cells[RedmineFields.created_on].Value2 = elements.issues[i - 1].created_on;

                    a.Cells[RedmineFields.done_ratio].Value2 = elements.issues[i - 1].done_ratio;
                    a.Cells[RedmineFields.due_date].Value2 = elements.issues[i - 1].due_date;
                    a.Cells[RedmineFields.estimated_hours].Value2 = elements.issues[i - 1].estimated_hours;
                    a.Cells[RedmineFields.id].Value2 = elements.issues[i - 1].id;
                    a.Cells[RedmineFields.priority].Value2 = elements.issues[i - 1].priority.name;
                    a.Cells[RedmineFields.project].Value2 = elements.issues[i - 1].project.name;
                    a.Cells[RedmineFields.start_date].Value2 = elements.issues[i - 1].start_date;
                    a.Cells[RedmineFields.status].Value2 = elements.issues[i - 1].status.name;
                    a.Cells[RedmineFields.subject].Value2 = elements.issues[i - 1].subject;
                    a.Cells[RedmineFields.tracker].Value2 = elements.issues[i - 1].tracker.name;
                    a.Cells[RedmineFields.updated_on].Value2 = elements.issues[i - 1].updated_on;
                    if (!Config.ExcludeDescription)
                        a.Cells[RedmineFields.description].Value2 = elements.issues[i - 1].description;

                }
                catch (Exception ex2)
                {

                    throw;

                }

                //todo   
                //for (int f = 0; i < elements.issues[i - 1].custom_fields.Count; f++)
                //{


                //}



            }



        }


        private List<JToken> DownloadRedmineElements(string address, string user, string pass, String baseToken)
        {
            var client = new WebClient();
            client.Credentials = new NetworkCredential(user, pass);

            var stringjson = client.DownloadString(address);
            JToken jToken = ((JObject)JsonConvert.DeserializeObject(stringjson))[baseToken];
            return jToken.ToList<JToken>();
        }

        private string DownloadRedmineJson(string address, string user, string pass, String baseToken)
        {
            var client = new WebClient();
            client.Credentials = new NetworkCredential(user, pass);

            var stringjson = client.DownloadString(address);

            return stringjson;
        }


        public string ExtractValueFromJtoken(JToken parent, string token, string subtoken)
        {
            string result;
            if (subtoken == "")
            {
                result = ((parent.SelectToken(token) == null) ? "" : parent.SelectToken(token).ToString());
            }
            else
            {
                result = ((parent.SelectToken(token) == null) ? "" : parent.SelectToken(token).SelectToken(subtoken).ToString());
            }
            return result;
        }

    }
}
